package com.tron.game.controllers;


import com.alibaba.fastjson.JSONObject;
import com.google.protobuf.ByteString;
import com.tron.game.configs.TronConfig;
import org.bouncycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.tron.trident.abi.FunctionEncoder;
import org.tron.trident.abi.FunctionReturnDecoder;
import org.tron.trident.abi.TypeReference;
import org.tron.trident.abi.datatypes.*;
import org.tron.trident.abi.datatypes.generated.Uint256;
import org.tron.trident.core.ApiWrapper;
import org.tron.trident.core.exceptions.IllegalException;
import org.tron.trident.core.transaction.TransactionBuilder;
import org.tron.trident.proto.Chain;
import org.tron.trident.proto.Contract;
import org.tron.trident.proto.Response;
import org.tron.trident.utils.Numeric;
import org.tron.trident.utils.Strings;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;

@RestController
@RequestMapping("/hello")
public class HelloController {
    @Autowired
    TronConfig tronConfig;

    @RequestMapping("/")
        String index() throws IllegalException {
        //Nile test net, using a node from Nile official website
        ApiWrapper wrapper = null;
        if("nile".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofNile(tronConfig.getPrivateKey());
        }else if("shasta".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofShasta(tronConfig.getPrivateKey());
        }else {
            wrapper= ApiWrapper.ofMainnet(tronConfig.getPrivateKey(),tronConfig.getApi_key());
        }

        Function askprice = new Function("askprice", Collections.emptyList(), Arrays.asList(new TypeReference<Uint>() {}));
        Response.TransactionExtention askprice_extension = wrapper.constantCall(tronConfig.getAddress(), tronConfig.getContract_address(), askprice);
        String askprice_result = Numeric.toHexString(askprice_extension.getConstantResult(0).toByteArray());
        BigInteger askprice_result1=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(0).getValue();


        return "Hello_"+askprice_result1;
    }
    @RequestMapping("/getCurrentRoundInfo")
    JSONObject getCurrentRoundInfo() throws IllegalException {
        //Nile test net, using a node from Nile official website
        ApiWrapper wrapper = null;
        if("nile".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofNile(tronConfig.getPrivateKey());
        }else if("shasta".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofShasta(tronConfig.getPrivateKey());
        }else {
            wrapper= ApiWrapper.ofMainnet(tronConfig.getPrivateKey(),tronConfig.getApi_key());
        }

        Function askprice = new Function("getCurrentRoundInfo", Collections.emptyList(), Arrays.asList(
                new TypeReference<Uint>() {},
                new TypeReference<Utf8String>() {},
                new TypeReference<Uint>() {},
                new TypeReference<Uint>() {},
                new TypeReference<Uint>() {},
                new TypeReference<Uint>() {},
                new TypeReference<Uint>() {},
                new TypeReference<Uint>() {},
                new TypeReference<Uint>() {},
                new TypeReference<Uint>() {},
                new TypeReference<Uint>() {},
                new TypeReference<Address>() {},
                new TypeReference<Uint>() {}

        ));
        Response.TransactionExtention askprice_extension = wrapper.constantCall(tronConfig.getAddress(), tronConfig.getContract_address(), askprice);
        String askprice_result = Numeric.toHexString(askprice_extension.getConstantResult(0).toByteArray());
        BigInteger game_id=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(0).getValue();
        String name=(String) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(1).getValue();
        BigInteger begin_time=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(2).getValue();
        BigInteger game_times=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(3).getValue();
        BigInteger last_buy_time=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(4).getValue();
        BigInteger over_time=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(5).getValue();

        BigInteger price=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(6).getValue();
        BigInteger price_upper_rate=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(7).getValue();
        BigInteger status=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(8).getValue();
        BigInteger prize_value=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(9).getValue();
        BigInteger buy_count=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(10).getValue();
        String last_buy_user_address=(String) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(11).getValue();
        BigInteger next_change_rate_count=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(12).getValue();

        JSONObject object = new JSONObject();

        //string
        object.put("game_id",game_id);
        object.put("name",name);
        object.put("begin_time",begin_time);
        object.put("begin_time_date",new Date(begin_time.longValue()*1000));

        object.put("game_times",game_times);
        object.put("last_buy_time",last_buy_time);
        object.put("last_buy_time_date",new Date(last_buy_time.longValue()*1000));

        object.put("over_time",over_time);
        object.put("over_time_date",new Date(over_time.longValue()*1000));

        object.put("price",price.longValue()/Math.pow(10,6));
        object.put("price_upper_rate",price_upper_rate.longValue()/Math.pow(10,18));
        object.put("prize_value",prize_value.longValue()/Math.pow(10,6));
        object.put("buy_count",buy_count);
        object.put("last_buy_user_address",last_buy_user_address);
        object.put("next_change_rate_count",next_change_rate_count);
        return object;



    }
    @RequestMapping("/checkGameAndPrize")
    String checkGameAndPrize()
    {
        ApiWrapper wrapper = null;
        if("nile".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofNile(tronConfig.getPrivateKey());
        }else if("shasta".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofShasta(tronConfig.getPrivateKey());
        }else {
            wrapper= ApiWrapper.ofMainnet(tronConfig.getPrivateKey(),tronConfig.getApi_key());
        }

        Function buy_token = new Function("checkGameAndPrize",Collections.emptyList(),Arrays.asList(new TypeReference<Bool>() {}));
        Response.TransactionExtention askprice_extension = wrapper.constantCall(tronConfig.getAddress(), tronConfig.getContract_address(), buy_token);
        String askprice_result = Numeric.toHexString(askprice_extension.getConstantResult(0).toByteArray());
        boolean askprice_result1=(boolean) FunctionReturnDecoder.decode(askprice_result, buy_token.getOutputParameters()).get(0).getValue();
        return  askprice_result1?"true":"false";
    }
    @RequestMapping("/getNow")
    long getNow()
    {
        ApiWrapper wrapper = null;
        if("nile".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofNile(tronConfig.getPrivateKey());
        }else if("shasta".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofShasta(tronConfig.getPrivateKey());
        }else {
            wrapper= ApiWrapper.ofMainnet(tronConfig.getPrivateKey(),tronConfig.getApi_key());
        }

        Function getNow = new Function("getNow",Collections.emptyList(),Arrays.asList(new TypeReference<Uint>() {}));
        Response.TransactionExtention askprice_extension = wrapper.constantCall(tronConfig.getAddress(), tronConfig.getContract_address(), getNow);
        String askprice_result = Numeric.toHexString(askprice_extension.getConstantResult(0).toByteArray());
        BigInteger now=(BigInteger) FunctionReturnDecoder.decode(askprice_result, getNow.getOutputParameters()).get(0).getValue();
        return  now.longValue();
    }
    @RequestMapping("/PrizeGame")
    String  PrizeGame()
    {
        ApiWrapper wrapper = null;
        if("nile".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofNile(tronConfig.getPrivateKey());
        }else if("shasta".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofShasta(tronConfig.getPrivateKey());
        }else {
            wrapper= ApiWrapper.ofMainnet(tronConfig.getPrivateKey(),tronConfig.getApi_key());
        }
        Function PrizeGame = new Function("PrizeGame",Collections.emptyList(),Arrays.asList(new TypeReference<Bool>() {}));
        String encodedHex = FunctionEncoder.encode(PrizeGame);
        Contract.TriggerSmartContract trigger =
                Contract.TriggerSmartContract.newBuilder()
                        .setOwnerAddress(ApiWrapper.parseAddress(tronConfig.getAddress()))
                        .setContractAddress(ApiWrapper.parseAddress(tronConfig.getContract_address()))
                        .setData(ApiWrapper.parseHex(encodedHex))
                        .build();
        Response.TransactionExtention txnExt = wrapper.blockingStub.triggerContract(trigger);


        TransactionBuilder builder = wrapper.triggerCall(tronConfig.getAddress(), tronConfig.getContract_address(), PrizeGame);
        builder.setTransaction(txnExt.getTransaction());
        builder.setFeeLimit(400000000L);
        Chain.Transaction transaction =builder.build();

        Chain.Transaction signedTxn = wrapper.signTransaction(transaction);
        String ret = wrapper.broadcastTransaction(signedTxn);


        return  "ok";
    }
    /**
     * 购买
     * @return
     */
    @RequestMapping("/buytoken")
    String Method1() {
        ApiWrapper wrapper = null;
        if("nile".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofNile(tronConfig.getPrivateKey());
        }else if("shasta".equals(tronConfig.getNetwork())) {
            wrapper= ApiWrapper.ofShasta(tronConfig.getPrivateKey());
        }else {
            wrapper= ApiWrapper.ofMainnet(tronConfig.getPrivateKey(),tronConfig.getApi_key());
        }
        Function askprice = new Function("askprice", Collections.emptyList(), Arrays.asList(new TypeReference<Uint>() {}));
        Response.TransactionExtention askprice_extension = wrapper.constantCall(tronConfig.getAddress(), tronConfig.getContract_address(), askprice);
        String askprice_result = Numeric.toHexString(askprice_extension.getConstantResult(0).toByteArray());
        BigInteger askprice_result1=(BigInteger) FunctionReturnDecoder.decode(askprice_result, askprice.getOutputParameters()).get(0).getValue();


        Function buy_token = new Function("buy_token",
                Arrays.asList(new Address(tronConfig.getAddress())),Arrays.asList(new TypeReference<Bool>() {}));

        String encodedHex = FunctionEncoder.encode(buy_token);
        Contract.TriggerSmartContract trigger =
                Contract.TriggerSmartContract.newBuilder()
                        .setOwnerAddress(ApiWrapper.parseAddress(tronConfig.getAddress()))
                        .setContractAddress(ApiWrapper.parseAddress(tronConfig.getContract_address()))
                        .setCallValue(askprice_result1.longValue())
                        .setData(ApiWrapper.parseHex(encodedHex))
                        .build();
        Response.TransactionExtention txnExt = wrapper.blockingStub.triggerContract(trigger);


        TransactionBuilder builder = wrapper.triggerCall(tronConfig.getAddress(), tronConfig.getContract_address(), buy_token);
        builder.setTransaction(txnExt.getTransaction());
        builder.setFeeLimit(300000000L);
        Chain.Transaction transaction =builder.build();

        Chain.Transaction signedTxn = wrapper.signTransaction(transaction);
        String ret = wrapper.broadcastTransaction(signedTxn);
        System.out.println("======== Result ========\n" + ret.toString());
        return  "ok";

    }



}